Ideam_Logo

Estaciones hidrometeorológicas


Introducción

En este cuadernillo (Notebook) aprenderemos:

  1. Introduccion a la red de monitoreo del IDEAM

  2. Cátalogo de estaciones de IDEAM

  3. Consulta de datos usando la plataforma datosabiertos.gov.co

  4. Consulta de datos de temperatura y precipitación

  5. Otros datos disponibles

Prerequisitos

Conceptos

Importancia

Notas

Introducción a Pandas

Necesario

lectura de datos tabulares

Introducción a Datetime

Necesario

Entender estampas de tiempo

Introducción a Cartopy

Necesario

Entender estampas de tiempo

Introducción a folium

Útil

Mapas interactivos

  • Tiempo de aprendizaje: 30 minutos

1. Catalogo nacional de estaciones de IDEAM

Según el catálogo de estaciones hidrometeorológicas de IDEAM, el pais cuenta con alrededor de 4.400 estaciones de diferentes categorias. En el siguiente cuadro se resume el estado de las estaciones por categoría de acuerdo a la PQR No. 20229050190832 (Enero de 2023)

Categoria

Activa

Mantenimiento

Suspendidas

Limnigráfica

287

109

106

Climátologica principal

215

60

92

Mareográfica

4

2

2

Pluviográfica

104

0

87

Limnimétrica

323

11

557

Climática Ordinaria

211

31

253

Agrometeorológica

51

4

57

Radio Sonda

6

2

2

Pluviométrica

1109

9

603

Meteorológica Especial

40

4

68

Sinóptica Principal

27

3

4

Sinóptica Secundaria

2

0

5

Total

2381

235

1866

Librerias

A continuación vamos a importar las librerias que utilizaremos en este cuadernillo

import pandas as pd
import cartopy.crs as ccrs
import cartopy.feature as feature
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
from pandas import to_datetime
from matplotlib.dates import HourLocator, DateFormatter

2. Acceso al catalogo en bart.ideam.gov.co

El catalogo nacional de estaciones de IDEAM actualizado se encuentra disponible en el servidor Bart. Podemos leer el catálogo usando pandas.read_excel como se muestra a continuación:

df_cat = pd.read_excel('http://bart.ideam.gov.co/cneideam/CNE_IDEAM.xls')
#df_cat.head()
df_cat.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4497 entries, 0 to 4496
Data columns (total 21 columns):
 #   Column                Non-Null Count  Dtype         
---  ------                --------------  -----         
 0   OBJECTID              4497 non-null   int64         
 1   CODIGO                4497 non-null   int64         
 2   nombre                4497 non-null   object        
 3   CATEGORIA             4497 non-null   object        
 4   TECNOLOGIA            4497 non-null   object        
 5   ESTADO                4497 non-null   object        
 6   FECHA_INSTALACION     4496 non-null   datetime64[ns]
 7   altitud               4497 non-null   int64         
 8   latitud               4497 non-null   float64       
 9   longitud              4497 non-null   float64       
 10  DEPARTAMENTO          4497 non-null   object        
 11  MUNICIPIO             4497 non-null   object        
 12  AREA_OPERATIVA        4497 non-null   object        
 13  AREA_HIDROGRAFICA     4497 non-null   object        
 14  ZONA_HIDROGRAFICA     4497 non-null   object        
 15  observacion           1335 non-null   object        
 16  CORRIENTE             4497 non-null   object        
 17  FECHA_SUSPENSION      1844 non-null   datetime64[ns]
 18  SUBZONA_HIDROGRAFICA  4497 non-null   object        
 19  ENTIDAD               4497 non-null   object        
 20  subred                1143 non-null   object        
dtypes: datetime64[ns](2), float64(2), int64(3), object(14)
memory usage: 737.9+ KB

2.1 Mapa de estaciones

Podemos usar cartopy para hacer un mapa y visualizar las estaciones de monitoreo en el pais

fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()}, dpi=150)
ax.coastlines()
gl = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree())
ax.scatter(df_cat['longitud'], df_cat['latitud'], transform=ccrs.PlateCarree(), s=.5)
ax.add_feature(feature.LAND)
ax.add_feature(feature.OCEAN)
ax.add_feature(feature.COASTLINE, linewidth=.5)
ax.add_feature(feature.BORDERS, linewidth=.5)
<cartopy.mpl.feature_artist.FeatureArtist at 0x7fa74bcdcd50>
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_land.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_ocean.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_coastline.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_cultural/ne_50m_admin_0_boundary_lines_land.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
../../_images/e224e413231bfb22b8513911359316f1d13a8f75aefe4c2beea4573892c27292.png

podemos agrupar la data por área operativa, tipo de estacion, tecnologia, y otras variables

# df_grp = df_cat.groupby('AREA_OPERATIVA')
# df_grp = df_cat.groupby('TECNOLOGIA')
df_grp = df_cat.groupby('ESTADO')
fig, ax = plt.subplots(subplot_kw={"projection":ccrs.PlateCarree()}, dpi=150)

for _, group in df_grp:
    ax.scatter(group['longitud'], group['latitud'], transform=ccrs.PlateCarree(), s=.5, label=_)
    
ax.coastlines()
gl = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree())
ax.add_feature(feature.LAND)
ax.add_feature(feature.OCEAN)
ax.add_feature(feature.COASTLINE, linewidth=.5)
ax.add_feature(feature.BORDERS, linewidth=.5)
ax.legend(fontsize=5)
<matplotlib.legend.Legend at 0x7fa74baefdd0>
../../_images/8adb57003b7a4e157063c5420ec0b73c0a726f7f53655ed7c01a4bcab75c7e83.png

Podemos validar el numero total de estaciones activas, en matenimiento y suspendidas de acuerdo con la información contenida en el catálogo

for grp in df_grp.groups.keys():
    print(f"{grp}: {len(df_grp.get_group(grp))}")
Activa: 2202
En Mantenimiento: 429
Suspendida: 1866

2.2 Mapa de estaciones interactivo

También podemos hacer mapas interactivos usando folium

import folium
from folium import plugins
from folium.plugins import MarkerCluster
min_lon, max_lon, min_lat, max_lat = -90, -72, -1, 14

map_ = folium.Map(location=[8, -76],
                  zoom_start = 6, 
                  min_lat=min_lat, 
                  max_lat=max_lat, 
                  min_lon=min_lon, 
                  max_lon=max_lon, 
                  zoom_control=False,
                  control_scale=True,
                  scrollWheelZoom=True,
                  width=1000,height=600)
marker_cluster = MarkerCluster(name="Estaciones").add_to(map_)

folium.TileLayer('cartodbpositron').add_to(map_)
folium.TileLayer('openstreetmap').add_to(map_)
folium.TileLayer('stamenterrain').add_to(map_)
folium.TileLayer('cartodbdark_matter').add_to(map_)
folium.LayerControl().add_to(map_)

minimap = plugins.MiniMap()
_ = map_.add_child(minimap)
# _

Ahora agregamos las estaciones usando la siguiente función

def plot_station(row):
    '''input: series that contains a numeric named latitude and a numeric named longitude
    this function creates a CircleMarker and adds it to your this_map'''
    
    html = row.to_frame("_").to_html(classes="table table-striped table-hover table-condensed table-responsive")
    popup = folium.Popup(html, max_width=2650)
    folium.Marker(location=[row.latitud, row.longitud], popup=popup).add_to(marker_cluster)
df_cat.apply(plot_station, axis=1)
map_
Make this Notebook Trusted to load map: File -> Trust Notebook

3. Acceso a la información historica de IDEAM usando datosabiertos.gov.co

la información historica de multiples sensores se puede consultar atraves de la plataforma de datos abiertos usando el aplicativo sodapy. Socrata utiliza un módulo denominado Socrata que permite realizar consultas al repositorio. Cada variable hidrometeorógica dispuesta se puede consultar usando el su respectivo código del set de datos.

Variable

Código del set de datos

Dirección del viento

kiw7-v9ta

Nivel instantaneo

bdmn-sqnh

Temperatura Minima del Aire

afdg-3zpb

Temperatura Maxima del Aire

ccvq-rp9s

Velocidad del Viento

sgfv-3yp8

Nivel Maximo

vfth-yucv

Nivel Minimo

pt9a-aamx

Humedad del Aire

uext-mhny

Temperatura

sbwg-7ju4

Nivel del mar mínimo

7z6g-yx9q

Nivel del mar máximo

uxy3-jchf

Nivel del mar

ia8x-22em

Presión Atmosferica

62tk-nxj5

Precipitación

s54a-sgyg

# importamos la libreria Socrata
from sodapy import Socrata

3.1 Precipitación (s54a-sgyg)

Vamos a consultar los datos de precipitación reportada en la página. por ende vamos a usar el código s54a-sgyg. Para esto usamos el metodo Socrata, pasamos la direccion del repositorio y None que corresponde a la no autenticación

# conexión cliente usando socrata al repositorio de datos abiertos
client = Socrata("www.datos.gov.co", None)
WARNING:root:Requests made without an app_token will be subject to strict throttling limits.

Una vez creado el cliente empezamos a hacer la consulta de datos usando client.get y pasando los respectivos parámetros dataset_identifier, de la tabla anterior , y limit para generar consultas no muy grandes para efectos demostrativos. El resultado es una lista con multiples diccionarios como se puede ver a continuación.

# Solicitud de informacion al repositorio de interés
results = client.get(dataset_identifier="s54a-sgyg", limit=2000)
results[:1]
[{'codigoestacion': '0023127020',
  'codigosensor': '0240',
  'fechaobservacion': '2009-10-17T17:20:00.000',
  'valorobservado': '0',
  'nombreestacion': 'PTO ARAUJO - RIO CARARE',
  'departamento': 'SANTANDER',
  'municipio': 'CIMITARRA',
  'zonahidrografica': 'MEDIO MAGDALENA',
  'latitud': '6.526',
  'longitud': '-74.086',
  'descripcionsensor': 'Precipitacion',
  'unidadmedida': 'mm'}]

Estos resultados los podemos convertir en un Dataframe usando pandas.Dataframe.from_records

results_df = pd.DataFrame.from_records(results)
results_df.head()
codigoestacion codigosensor fechaobservacion valorobservado nombreestacion departamento municipio zonahidrografica latitud longitud descripcionsensor unidadmedida
0 0023127020 0240 2009-10-17T17:20:00.000 0 PTO ARAUJO - RIO CARARE SANTANDER CIMITARRA MEDIO MAGDALENA 6.526 -74.086 Precipitacion mm
1 0021055501 0240 2017-10-10T13:40:00.000 0 SIMON CAMPOS - AUT HUILA LA PLATA ALTO MAGDALENA 2.345830556 -75.87805556 Precipitacion mm
2 0035075080 0240 2018-01-09T00:30:00.000 0 PARAMO RABANAL - AUT BOYACÁ VENTAQUEMADA META 5.392388889 -73.56277778 Precipitacion mm
3 0011017020 0240 2019-06-16T07:10:00.000 0 PR CHOCO: BAGADO CHOCÓ BAGADÓ <nil> 5.412 -76.418 Precipitacion mm
4 0057015010 0240 2017-10-14T22:00:00.000 0 MALPELO - DIMAR VALLE DEL CAUCA BUENAVENTURA BAUDÓ - DIRECTOS PACIFICO 4.096 -81.609 Precipitacion mm

Ahora podemos usar filtrar los datos por diferentes campos como el codigoestacion, fechaobservacion, o valorobservado. Podemos pasar parametros SQL como where, AND, IN, entre otros, en el método client.get

# client.get?
# Solicitud de informacion para la estación de la Universidad Nacional - Bogotá - 0021205012
ppt_query = client.get(dataset_identifier="s54a-sgyg", 
                       select="fechaobservacion, valorobservado, codigoestacion", 
                       where="codigoestacion IN ('0021205012') \
                              AND fechaobservacion > '2017'")
df_est = pd.DataFrame.from_records(ppt_query)
df_est.head()
fechaobservacion valorobservado codigoestacion
0 2017-06-15T01:00:00.000 0 0021205012
1 2018-07-04T13:20:00.000 0 0021205012
2 2019-08-16T05:50:00.000 0 0021205012
3 2017-01-13T11:30:00.000 0 0021205012
4 2017-08-31T14:40:00.000 0 0021205012

Gráfico de la serie temporal

Podemos generar una serie temporal usando la información resultado de la consulta. Sin embargo, primero debemos revisar el tipo de dato de cada columna

df_est.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 3 columns):
 #   Column            Non-Null Count  Dtype 
---  ------            --------------  ----- 
 0   fechaobservacion  1000 non-null   object
 1   valorobservado    1000 non-null   object
 2   codigoestacion    1000 non-null   object
dtypes: object(3)
memory usage: 23.6+ KB
df_est['fechaobservacion'] = pd.to_datetime(df_est['fechaobservacion'])
df_est.set_index('fechaobservacion', inplace=True)
df_est.valorobservado = df_est['valorobservado'].astype(float)
df_est = df_est.sort_index()
df_est.tail()
valorobservado codigoestacion
fechaobservacion
2019-08-24 08:50:00 0.0 0021205012
2019-08-26 11:30:00 0.0 0021205012
2019-08-26 14:00:00 0.0 0021205012
2019-08-27 16:00:00 0.0 0021205012
2019-08-27 19:20:00 0.0 0021205012
# pd.options.plotting.backend = 'holoviews'
fig, ax = plt.subplots(figsize=(12, 3))
df_est['valorobservado'].plot(ax=ax, drawstyle="steps")
<Axes: xlabel='fechaobservacion'>
../../_images/fec9e9bcf237fe29e3bd052000372ae84f529036dde4a73486bcc1bf5feeaef5.png

Podemos solicitar informacion para estaciones que reportan datos en el último més

ppt_query = client.get(dataset_identifier="s54a-sgyg", 
                       select="fechaobservacion, valorobservado, codigoestacion, nombreestacion", 
                       where="fechaobservacion > '2023-09-11'")
df_ult = pd.DataFrame.from_records(ppt_query)
df_ult.head()
fechaobservacion valorobservado codigoestacion nombreestacion
0 2023-09-11T00:01:00.000 0 3502500135 GUAYABETAL POLLO OLIMPICO - AUT
1 2023-09-11T00:03:00.000 0 3502500135 GUAYABETAL POLLO OLIMPICO - AUT
2 2023-09-11T00:04:00.000 0 3502500135 GUAYABETAL POLLO OLIMPICO - AUT
3 2023-09-11T00:05:00.000 0 0026177030 LA VIRGINIA
4 2023-09-11T00:05:00.000 0 3502500135 GUAYABETAL POLLO OLIMPICO - AUT

3.2 Temperatura (sbwg-7ju4)

De manera similar podemos consultar otros registros como los de temperatura. Cambiamos el identificador de set de datos y generamos una nueva consulta

# Solicitud de informacion para la estación de la Universidad Nacional - Bogotá - 0021205012
temp_query = client.get(dataset_identifier="sbwg-7ju4", 
                       select="fechaobservacion, valorobservado, codigoestacion", 
                       where="codigoestacion IN ('0021205012') \
                              AND fechaobservacion > '2017'")
df_temp = pd.DataFrame.from_records(temp_query)
df_temp.index = pd.to_datetime(df_temp['fechaobservacion'])
df_temp.valorobservado = df_temp['valorobservado'].astype(float)
df_temp = df_temp.sort_index()
df_temp.tail()
fechaobservacion valorobservado codigoestacion
fechaobservacion
2020-01-22 08:00:00 2020-01-22T08:00:00.000 13.6 0021205012
2020-01-22 10:00:00 2020-01-22T10:00:00.000 18.1 0021205012
2020-01-22 12:00:00 2020-01-22T12:00:00.000 17.6 0021205012
2020-01-22 16:00:00 2020-01-22T16:00:00.000 17.7 0021205012
2020-01-22 21:00:00 2020-01-22T21:00:00.000 13.8 0021205012
fig, ax = plt.subplots(figsize=(12, 3))
df_temp['valorobservado'].plot(c='C00', lw=0.5, ax=ax)
<Axes: xlabel='fechaobservacion'>
../../_images/c9d32fa9be82de501ac6d7880231454dff857a2fa7b16a5db68fc7a26825bab1.png

4. Datos en tiempo “Causireal” de IDEAM

De igual manera, el Ideam dispone de una tabla de datos en tiempo cercano a la medición. Esta tabla corresponde al dataset_identifier="57sv-p2fu". Generemos una consulta básica para ver los campos contenidos dentro de esta tabla en el último día

time_now = datetime.now()
time = time_now - timedelta(days=1)
time
datetime.datetime(2023, 10, 11, 17, 15, 31, 779728)

Convertimos la fecha en un str para incluirlo en la consulta

time_str = f"{to_datetime(time):%Y-%m-%d}"
time_str
'2023-10-11'
nrt_query = client.get(dataset_identifier="57sv-p2fu", 
                        select="*", 
                        where="fechaobservacion >= '{}'".format(time_str),
                        limit=2000)
df_nrt = pd.DataFrame.from_records(nrt_query)
df_nrt.head()
codigoestacion codigosensor fechaobservacion valorobservado nombreestacion departamento municipio zonahidrografica latitud longitud descripcionsensor unidadmedida
0 0035095130 0069 2023-10-12T07:40:00.000 3 LAGUNA LA PLAZA ARAUCA SARAVENA CASANARE 6.362 -72.28201667 TEMPERATURA DEL AIRE MÁXIMA A 2 m °C
1 0051027060 0230 2023-10-12T05:00:00.000 1.88 SAN JUAN MIRA NARIÑO TUMACO MIRA 1.42388889 -78.67027778 NIVEL INSTANTANEO mt
2 0021125010 0104 2023-10-11T11:50:00.000 4 SANTA MARIA HUILA SANTA MARÍA ALTO MAGDALENA 2.93569444 -75.58905556 DIRECCIÓN DEL VIENTO GN
3 0014015080 0240 2023-10-11T21:30:00.000 0 AEROPUERTO RAFAEL NUNEZ BOLÍVAR CARTAGENA DE INDIAS CARIBE - LITORAL 10.44725 -75.51602778 PRECIPITACIÓN mm
4 0035060210 0103 2023-10-12T02:50:00.000 0.9 CLARAVAL CUNDINAMARCA JUNÍN META 4.65025 -73.64144444 VELOCIDAD DEL VIENTO m/s

Los primeros registros nos indican que hay mediciones cercanas a las fechas de la ejecución de este cuadernillo. Generemos una consulta más específica para la estacion 0024035340 correspindiente al Aeropuerto Alberto Lleras Camargo de Sogamoso.

cod_est = '0024035340'
aero_query = client.get(dataset_identifier="57sv-p2fu", 
                        select="*", 
                        where="fechaobservacion >= '{}'\
                        AND codigoestacion IN ('{}')".format(time_str, cod_est),
                        limit=2000)
df_aero = pd.DataFrame.from_records(aero_query)
df_aero.head(10)
codigoestacion codigosensor fechaobservacion valorobservado nombreestacion departamento municipio zonahidrografica latitud longitud descripcionsensor unidadmedida
0 0024035340 0069 2023-10-11T11:11:00.000 19.8 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 TEMPERATURA DEL AIRE MÁXIMA A 2 m °C
1 0024035340 0070 2023-10-11T11:30:00.000 18.9 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 TEMPERATURA MÍNIMA DEL AIRE A 2 m °C
2 0024035340 0103 2023-10-11T12:10:00.000 4.6 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 VELOCIDAD DEL VIENTO m/s
3 0024035340 0240 2023-10-11T12:10:00.000 0 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 PRECIPITACIÓN mm
4 0024035340 0104 2023-10-11T12:10:00.000 180 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 DIRECCIÓN DEL VIENTO GN
5 0024035340 0070 2023-10-11T12:10:00.000 18.9 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 TEMPERATURA MÍNIMA DEL AIRE A 2 m °C
6 0024035340 0258 2023-10-11T12:18:00.000 759.3 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - PRESIÓN ATMOSFÉRICA hPA
7 0024035340 0111 2023-10-11T12:18:00.000 5.9 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - VELOCIDAD DEL VIENTO m/s
8 0024035340 0071 2023-10-11T12:18:00.000 19 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - TEMPERATURA DEL AIRE A 2 m °C
9 0024035340 0257 2023-10-11T12:18:00.000 0 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - PRECIPITACIÓN mm

Para validar los sensores que tiene esta estacion podemo usar el método .unique() de Pandas

df_aero.codigosensor.unique()
array(['0069', '0070', '0103', '0240', '0104', '0258', '0111', '0071',
       '0257', '0028', '0255', '0027', '0068'], dtype=object)

Podemos centrar aún mas la consulta agregandole el sensor de temperatura codigosensor=0071

cod_sensor = '0071'
aero_query = client.get(dataset_identifier="57sv-p2fu", 
                        select="fechaobservacion, valorobservado", 
                        where="fechaobservacion >= '{}'\
                        AND codigoestacion IN ('{}') \
                        AND codigosensor IN ('{}')".format(time_str, cod_est, cod_sensor),
                        limit=2000)
df_aero = pd.DataFrame.from_records(aero_query)
df_aero
fechaobservacion valorobservado
0 2023-10-11T12:18:00.000 19
1 2023-10-11T12:20:00.000 19.1
2 2023-10-11T12:22:00.000 19.2
3 2023-10-11T12:24:00.000 19.1
4 2023-10-11T12:26:00.000 19
... ... ...
714 2023-10-12T12:06:00.000 22.3
715 2023-10-12T12:08:00.000 22.1
716 2023-10-12T12:10:00.000 21.8
717 2023-10-12T12:12:00.000 22.5
718 2023-10-12T12:14:00.000 23

719 rows × 2 columns

Ahora generemos un gráfico rápido de la serie de precipitacion para las ultimas 24 horas

fig, ax = plt.subplots(figsize=(10, 3))
df_aero.index = pd.to_datetime(df_aero['fechaobservacion'])
df_aero.valorobservado = df_aero['valorobservado'].astype(float)
df_aero.plot(ax=ax)
ax.xaxis.set_major_locator(HourLocator(interval=4)) # tick every four hours
ax.xaxis.set_major_formatter(DateFormatter('%m-%d\n%H:%M'))
../../_images/c36c4fcd913e0625ef1d37bcca65beea820759a2fd2a98cf13868a6ce56d6964.png

Conclusiones

En este cuadernillo aprendimos una manera fácil y rápida para acceder a la información histórica y presente de las estaciones hidrometeorológicas de IDEAM. De igual modo aprendimos a visualizar las estaciones usando mapas interactivos. También aprendimos a generar consultas a diferentes grupos de datos usando sintaxis SQL y el aplicativo socrata de la plataforma de datos abiertos del gobierno colombiano.

Resources and references

  • Rose, B. E. J., Kent, J., Tyle, K., Clyne, J., Banihirwe, A., Camron, D., May, R., Grover, M., Ford, R. R., Paul, K., Morley, J., Eroglu, O., Kailyn, L., & Zacharias, A. (2023). Pythia Foundations (Version v2023.05.01) https://doi.org/10.5281/zenodo.7884572